/**
 * ECS架构核心 - Entity Component System
 */

export interface Component {}

export interface System {
  priority?: number;
  init?(world: World): void;
  update(deltaTime: number, world: World): void;
}

let nextEntityId = 1;

export class Entity {
  readonly id: number = nextEntityId++;
  private components = new Map<string, Component>();
  public active = true;

  /**
   * 添加组件
   */
  addComponent<T extends Component>(key: string, component: T): this {
    this.components.set(key, component);
    return this;
  }

  /**
   * 获取组件
   */
  getComponent<T extends Component>(key: string): T | undefined {
    return this.components.get(key) as T;
  }

  /**
   * 检查是否有组件
   */
  hasComponent(key: string): boolean {
    return this.components.has(key);
  }

  /**
   * 移除组件
   */
  removeComponent(key: string): void {
    this.components.delete(key);
  }

  /**
   * 销毁实体
   */
  destroy(): void {
    this.active = false;
  }
}

export interface GameResources {
  canvas: HTMLCanvasElement;
  ctx: CanvasRenderingContext2D;
  input: import('../input/Input').Input;
  width: number;
  height: number;
  deltaTime: number;
}

export class World {
  public entities: Set<Entity> = new Set();
  public systems: System[] = [];
  public resources: GameResources;

  constructor(resources: GameResources) {
    this.resources = resources;
  }

  /**
   * 添加实体
   */
  addEntity(entity: Entity): Entity {
    this.entities.add(entity);
    return entity;
  }

  /**
   * 移除实体
   */
  removeEntity(entity: Entity): void {
    this.entities.delete(entity);
  }

  /**
   * 添加系统
   */
  addSystem(system: System): void {
    this.systems.push(system);
    // 按优先级排序
    this.systems.sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0));
    system.init?.(this);
  }

  /**
   * 更新世界
   */
  update(deltaTime: number): void {
    this.resources.deltaTime = deltaTime;
    
    // 清理已销毁的实体
    for (const entity of Array.from(this.entities)) {
      if (!entity.active) {
        this.entities.delete(entity);
      }
    }

    // 更新所有系统
    for (const system of this.systems) {
      system.update(deltaTime, this);
    }
  }
}